home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / jockguts.arc / PULLTTT5.PAS < prev    next >
Pascal/Delphi Source File  |  1991-04-28  |  29KB  |  744 lines

  1. {--------------------------------------------------------------------------}
  2. {                         TechnoJock's Turbo Toolkit                       }
  3. {                                                                          }
  4. {                              Version   5.01                              }
  5. {                                                                          }
  6. {                                                                          }
  7. {              Copyright 1986, 1989 TechnoJock Software, Inc.              }
  8. {                           All Rights Reserved                            }
  9. {                          Restricted by License                           }
  10. {--------------------------------------------------------------------------}
  11.  
  12.                      {--------------------------------}
  13.                      {       Unit:  PullTTT5          }
  14.                      {--------------------------------}
  15.  
  16.  
  17. {$S-,R-,V-,D-}
  18. {Change History:    4/01/89   5.01   Added DOS errorlevel of 12 on fatal
  19.                                      error - line 186
  20.                               5.01   Changed type def of Sub_Menu to
  21.                                      Max_Pull_Width - line 144
  22.                               5.01   Changed error message 6  - line 180
  23. }
  24. unit PullTTT5;
  25.  
  26. Interface
  27.  
  28. Uses CRT, DOS, FastTTT5, WinTTT5, KeyTTT5;
  29.  
  30. Const
  31.     Max_Pull_Topics = 60;
  32.     Max_Pull_Width  = 30;
  33. type
  34.     Pull_Array = array [1..Max_Pull_Topics] of string[Max_Pull_Width];
  35.     {$IFDEF VER50}
  36.      Pull_Hook = Procedure(var Ch: char; Main, Sub :byte);
  37.     {$ENDIF}
  38.     MenuDisplay = record
  39.                      TopX:byte;
  40.                      TopY:byte;
  41.                      Style:byte;
  42.                      FCol: byte;       {normal option foreground color}
  43.                      BCol: byte;       {normal option background color}
  44.                      CCol: byte;       {color of first Character}
  45.                      MBCol: byte;      {highlight bgnd col for main pick when sub-menu displayed}
  46.                      HFCol: byte;      {highlighted option foreground}
  47.                      HBCol: byte;      {highlighted option background}
  48.                      BorCol: byte;     {border foreground color}
  49.                      Gap   : byte;     {Gap between Picks}
  50.                      LeftChar    : char;     {left-hand topic highlight character}
  51.                      RightChar   : char;     {right-hand topic highlight character}
  52.                      AllowEsc    : boolean; {is Escape key operative}
  53.                      RemoveMenu  : boolean;{clear screen on exit}
  54.                      AlwaysDown : boolean;
  55.                      {$IFDEF VER50}
  56.                      Hook         : Pull_hook;
  57.                      {$ENDIF}
  58.                   end;
  59. Const
  60.     Max_MainPicks = 8;
  61.     Max_Subpicks  = 10;
  62.     MainInd = '\';           {symbol that indicates main menu description}
  63.  
  64. Var
  65.   PTTT : MenuDisplay;
  66.  
  67.   {$IFNDEF VER50}
  68.   PM_UserHook : pointer;
  69.   {$ENDIF}
  70.  
  71. {$IFDEF VER50}
  72. Procedure No_Hook(var Ch: char; Main, Sub :byte);
  73. {$ENDIF}
  74.  
  75. Procedure Pull_Menu( Definition:Pull_Array; var PickM, PickS:byte);
  76.  
  77.  
  78. Implementation
  79.  
  80.   {$IFDEF VER50}
  81.   {$F+}
  82.   Procedure No_Hook(var Ch: char; Main, Sub :byte);
  83.   {}
  84.   begin
  85.   end; {of proc No_Hook}
  86.   {$F-}
  87.   {$ENDIF}
  88.  
  89.    {$IFNDEF VER50}
  90.    Procedure CallFromPM(var Ch: char; Main, Sub :byte);
  91.           Inline($FF/$1E/PM_UserHook);
  92.    {$ENDIF}
  93.  
  94.    Procedure Default_Settings;
  95.    begin
  96.        {$IFNDEF VER50}
  97.        PM_UserHook := nil;
  98.        {$ENDIF}
  99.        With PTTT do
  100.        begin
  101.            {$IFDEF VER50}
  102.            Hook := No_Hook;
  103.            {$ENDIF}
  104.            TopY := 1;
  105.            TopX := 1;
  106.            Style := 1;
  107.            Gap := 2;
  108.            LeftChar := #016;
  109.            RightChar := #017;
  110.            AllowEsc := true;
  111.            RemoveMenu := true;
  112.            AlwaysDown := true;
  113.            If BaseOfScreen = $b000 then {monochrome}
  114.            begin
  115.                FCol  := lightgray;
  116.                BCol  := black;
  117.                CCol  := white;
  118.                MBCol  := lightgray;
  119.                HFCol  := black;
  120.                HBCol  := lightgray;
  121.                BorCol := lightgray;
  122.            end
  123.            else                    {color}
  124.            begin
  125.                FCol  := yellow;
  126.                BCol  := blue;
  127.                CCol  := lightcyan;
  128.                MBCol  := red;
  129.                HFCol  := yellow;
  130.                HBCol  := red;
  131.                BorCol := cyan;
  132.            end;
  133.       end;
  134.   end; {Proc Default_Settings}
  135.  
  136.  
  137. Procedure Pull_Menu(Definition: Pull_Array; var PickM, PickS:byte);
  138. const
  139.     CursUp = #200  ;  CursDown = #208  ;  CursLeft = #203  ;   CursRight = #205;
  140.     HomeKey = #199 ;  Endkey   = #207  ;  Esc      = #027  ;   Enter     = #13;
  141.     F1      = #187 ;
  142.  
  143. type
  144.    Sub_details = record
  145.                     Text:  Array[0..Max_SubPicks] of string[Max_Pull_Width];     {5.01}
  146.                     Total: byte;
  147.                     Width: byte;
  148.                     LastPick: byte;
  149.                  end;
  150. var
  151.   Submenu  : array [1..Max_MainPicks] of Sub_Details;
  152.   Tot_main : byte;              {total number of main picks}
  153.   Main_Wid : byte;              {width of main menu box}
  154.   Finished,                     {has user selected menu option}
  155.   Down     : boolean;           {indicates if sub-menu displayed}
  156.   ChM,ChT      : char;          {keypressed character}
  157.   X1, Y1, X2, Y2 : byte;        {lower menu borders}
  158.   Cap,Count      : byte;        {used to check if letter pressed = first char}
  159.   Saved_Screen : Pointer;
  160.   I                 : integer;
  161.   TLchar,           {border submenu upper left char}
  162.   TRchar,           {border submenu upper right char}
  163.   BLchar,           {border submenu bottom left char}
  164.   BRchar,           {border submenu bottom right char}
  165.   Joinchar,         {border joining character}
  166.   Joindownchar,     {border joining character}
  167.   JoinleftChar,     {border joining character}
  168.   VertChar,         {border vert character}
  169.   Horizchar:char;   {border horiz char}
  170.  
  171.  
  172.     Procedure PullError(No : byte);
  173.     var M : string;
  174.     begin
  175.         Case No of
  176.         1 : M := 'Menu definiton must start with a Main ("\") description';
  177.         2 : M := 'Main menu definition must be at least 1 character';
  178.         3 : M := 'Too many main menu picks.';
  179.         4 : M := 'Too many sub-menu picks.';
  180.         5 : M := 'No end of menu indicator found';
  181.         6 : M := 'Must be at least two main menu picks';   {5.01}
  182.         7 : M := 'Main menu will not fit in 80 characters';
  183.         8 : M := 'No memory to save screen';
  184.         end; {case}
  185.         Writeln;
  186.         Writeln(M);
  187.         Halt(12);           {5.01}
  188.     end; {Abort}
  189.  
  190.     Procedure Set_Style;
  191.     {Sets variables for the box characters based on defined style}
  192.     begin
  193.         Case PTTT.Style of
  194.         1  :  begin
  195.                   TLchar := #218;
  196.                   TRchar := #191;
  197.                   BLchar := #192;
  198.                   BRchar := #217;
  199.                   Joinchar := #194;
  200.                   Joindownchar := #193;
  201.                   JoinleftChar := #180;
  202.                   VertChar := #179;
  203.                   Horizchar := #196;
  204.               end;
  205.         2  :  begin
  206.                   TLchar := #201;
  207.                   TRchar := #187;
  208.                   BLchar := #200;
  209.                   BRchar := #188;
  210.                   Joinchar := #203;
  211.                   Joindownchar := #202;
  212.                   JoinleftChar := #185;
  213.                   VertChar := #186;
  214.                   Horizchar := #205;
  215.               end;
  216.         else
  217.              begin
  218.                   TLchar := ' ';
  219.                   TRchar := ' ';
  220.                   BLchar := ' ';
  221.                   BRchar := ' ';
  222.                   Joinchar := ' ';
  223.                   Joindownchar := ' ';
  224.                   JoinleftChar := ' ';
  225.                   VertChar := ' ';
  226.                   Horizchar := ' ';
  227.               end;
  228.         end; {Case}
  229.     end;  {Proc Set_Style}
  230.  
  231.     Procedure Save_Screen;
  232.     {saved part of screen overlayed by menu}
  233.     begin
  234.         If MaxAvail < DisplayLines*160 then
  235.            PullError(8)
  236.         else
  237.         begin
  238.             GetMem(Saved_Screen,DisplayLines*160);
  239.             PartSave(1,1,80,DisplayLines,Saved_Screen^);
  240.         end;
  241.     end; {of proc Save_Screen}
  242.  
  243.     Procedure PartRestoreScreen(X1,Y1,X2,Y2:byte);
  244.     {Move from heap to screen, part of saved screen}
  245.     Var
  246.        I,width     : byte;
  247.        ScreenAdr   : integer;
  248.     begin
  249.         Width := succ(X2- X1);
  250.         For I :=  Y1 to Y2 do
  251.         begin
  252.             ScreenAdr   := Pred(I)*160 + Pred(X1)*2;
  253.             MoveToScreen(Mem[Seg(Saved_Screen^):ofs(Saved_Screen^)+SCreenAdr],
  254.                          Mem[BaseOfScreen:ScreenAdr],
  255.                          width);
  256.         end;
  257.     end;
  258.  
  259.       Procedure Restore_Screen;
  260.       {saved part of screen overlayed by menu}
  261.       begin
  262.           PartRestore(1,1,80,DisplayLines,Saved_Screen^);
  263.       end;
  264.  
  265.       Procedure Dispose_Screen;
  266.       {}
  267.       begin
  268.           FreeMem(Saved_Screen,DisplayLines*160);
  269.       end;
  270.  
  271.     Procedure Load_Menu_Parameters;
  272.     { converts the MenuDesc array into the Sub_menu array, and
  273.       determines Tot_main
  274.     }
  275.     var
  276.       I, Maj, Min, Widest : integer;
  277.       Instr : string[30];
  278.       Finished : Boolean;
  279.     begin
  280.         FillChar(Submenu,sizeof(Submenu),#0);
  281.         Tot_main := 0;
  282.         If Definition[1][1] <> '\' then PullError(1);
  283.         Maj := 0;
  284.         Widest := 0;
  285.         I := 0;
  286.         Finished := false;
  287.         While (I < Max_Pull_Topics) and (Finished=false) do
  288.         begin
  289.             Inc(I);
  290.             If Definition[I] <> '' then
  291.             begin
  292.                 Instr := Definition[I];
  293.                 If Instr[1] = MainInd then
  294.                 begin
  295.                     If Maj <> 0 then           {update values for last sub menu}
  296.                     begin
  297.                         SubMenu[Maj].Total := Min;
  298.                         SubMenu[Maj].Width := widest;
  299.                     end;
  300.                     If length(Instr) < 2 then PullError(2);
  301.                     If Instr = Mainind + mainind then   {must have loaded all data}
  302.                     begin                               {note number of main menu }
  303.                         Tot_main := Maj;                   {picks and exit}
  304.                         Finished := true;
  305.                     end;
  306.                     Maj := succ(Maj);
  307.                     If Maj > Max_mainpicks then PullError(3);
  308.                     delete(Instr,1,1);
  309.                     SubMenu[Maj].text[0] := Instr;
  310.                     Min := 0;                      {reset values for next sub heading}
  311.                     Widest := 0;
  312.                 end
  313.                 else         {not a main menu heading}
  314.                 begin
  315.                     Min := succ(Min);
  316.                     If Min > Max_SubPicks then PullError(4);
  317.                     SubMenu[Maj].text[Min] := Instr;
  318.                     If length(Instr) > widest then
  319.                        widest := length(Instr);
  320.                 end;   {if main heading}
  321.             end;
  322.         end; {while}
  323.         If Tot_main = 0 then PullError(5);
  324.         If Tot_main < 2 then PullError(6);
  325.    end; {sub-proc Load_Menu_Parameters}
  326.  
  327.    Function First_Capital(InStr:string; Var StrPos:byte):char;
  328.    {returns the first capital letter in a string and Character position}
  329.    begin
  330.        StrPos := 1;
  331.        While (StrPos <= length(InStr))  and ((InStr[StrPos] in [#65..#90]) = false) do
  332.               StrPos := Succ(StrPos);
  333.        If StrPos > length(InStr) then
  334.        begin
  335.            StrPos := 0;
  336.            First_Capital := ' ';
  337.        end
  338.        else
  339.           First_Capital := InStr[StrPos];
  340.    end;   {First_Capital}
  341.  
  342.    Procedure Display_Main_Picks(No : byte; Col : byte);
  343.    { displays main heading for menu pick 'No', if Col = 1 then
  344.      PTTT.HFCol and PTTT.MBCol cols are used without arrows, else PTTT.FCol and PTTT.BCol
  345.      colors are used}
  346.    var
  347.      ChT : Char;
  348.      X, I, B : byte;
  349.    begin
  350.        X := 1;
  351.        If No = 1 then
  352.           X := X + PTTT.TopX + PTTT.Gap
  353.        else
  354.        begin
  355.            For I := 1 to No - 1 do
  356.                X := X + length(Submenu[I].Text[0]) + PTTT.Gap;
  357.            X := X + PTTT.TopX  + PTTT.Gap ;
  358.        end;
  359.        If Col > 0 then
  360.           Fastwrite(X,PTTT.TopY+ord(PTTT.Style>0),attr(PTTT.HFCol,PTTT.MBCol),
  361.                     Submenu[No].Text[0])
  362.        else
  363.        begin
  364.            Fastwrite(X,PTTT.TopY+ord(PTTT.Style>0),attr(PTTT.FCol,PTTT.BCol),
  365.                      +Submenu[No].Text[0]);
  366.            ChT := First_Capital(Submenu[No].Text[0],B);
  367.            If B <> 0 then
  368.               FastWrite(pred(X)+B,PTTT.TopY+ord(PTTT.Style>0),
  369.                         attr(PTTT.CCol,PTTT.BCol),ChT);
  370.        end;
  371.        GotoXY(X,PTTT.TopY+Ord(PTTT.Style>0));
  372.    end; {Display Main Header}
  373.  
  374.    Procedure Display_Main_Menu;
  375.    {draws boxes, main menu picks and draws border}
  376.    var I : byte;
  377.    begin
  378.        {draw the box}
  379.        Main_Wid := succ(PTTT.Gap) ;           {determine the width of the main menu}
  380.        For I := 1 to Tot_Main do
  381.            Main_Wid := Main_Wid + PTTT.Gap + length(Submenu[I].text[0]);
  382.        If Main_Wid + PTTT.TopX - 1 > 80 then PullError(7);
  383.        If PTTT.Style = 0 then
  384.           ClearText(PTTT.TopX,PTTT.TopY,PTTT.TopX + Main_Wid,PTTT.TopY,PTTT.BorCol,PTTT.BCol)
  385.        else
  386.           Fbox(PTTT.TopX,PTTT.TopY,PTTT.TopX + Main_Wid,PTTT.TopY + 2,PTTT.BorCol,PTTT.BCol,PTTT.Style);
  387.        For I := 1 to ToT_Main do
  388.            Display_Main_Picks(I,0);
  389.        Display_Main_Picks(PickM,1);
  390.    end;  {Display_Main_Menu}
  391.  
  392.    Procedure Remove_Sub_Menu;
  393.    var a : integer;
  394.    begin
  395.        Fastwrite(X1,PTTT.TopY+2,attr(PTTT.BorCol,PTTT.BCol),horizchar);
  396.        Fastwrite(X2,PTTT.TopY+2,attr(PTTT.BorCol,PTTT.BCol),horizchar);
  397.        PartRestoreSCreen(PTTT.TopX, succ(PTTT.TopY)+2*ord(PTTT.Style>0), 80, DisplayLines);
  398.        If (PTTT.Style > 0 ) and (X2 >= PTTT.TopX + Main_wid) then
  399.        begin
  400.            A := PTTT.TopX +Main_Wid + 1;
  401.            PartRestoreScreen(A, PTTT.TopY + 2, 80, PTTT.TopY + 2);
  402.            Fastwrite(A - 1, PTTT.TopY+2, attr(PTTT.BorCol,PTTT.BCol),BRchar);
  403.        end;
  404.        SubMenu[PickM].LastPick := PickS;
  405.    end;
  406.  
  407.    Procedure Display_Sub_Picks(No : byte; Col : byte);
  408.    { displays sub  menu pick 'No', if Col = 1 then
  409.      PTTT.HFCol and PTTT.HBCol cols are used and arrows, else PTTT.FCol and PTTT.BCol
  410.      colors are used}
  411.    var
  412.      ChT : Char;
  413.      B : Byte;
  414.    begin
  415.        If Col = 1 then
  416.           Fastwrite(X1 + 1, succ(PTTT.TopY)+ord(PTTT.Style>0) + No ,
  417.                     attr(PTTT.HFCol,PTTT.HBCol),
  418.                     PTTT.LeftChar + Submenu[PickM].Text[No] + PTTT.Rightchar)
  419.        else
  420.        begin
  421.           Fastwrite(X1 + 1, succ(PTTT.TopY)+Ord(PTTT.Style>0) + No ,
  422.                     attr(PTTT.FCol,PTTT.BCol),
  423.                     ' '+Submenu[PickM].Text[No]+' ');
  424.           ChT := First_Capital(SubMenu[PickM].Text[No],B);
  425.           If B <> 0 then
  426.              FastWrite(X1+1+B,succ(PTTT.TopY)+Ord(PTTT.Style>0) + No ,
  427.                        attr(PTTT.CCol,PTTT.BCol),ChT);
  428.        end;
  429.        GotoXY(X1+1,succ(PTTT.TopY)+ord(PTTT.Style>0)+ No);
  430.    end;
  431.  
  432.  
  433.    Procedure Display_Sub_Menu(No :byte);
  434.    var
  435.      BotLine : string;
  436.      I : byte;
  437.    begin
  438.        If (Submenu[pickM].Total = 0) then
  439.            exit
  440.        else
  441.            Down := true;
  442.        X1 := pred(PTTT.TopX);                    {determine box coords of sub menu}
  443.        If No <> 1 then
  444.        begin
  445.            For I := 1 to pred(No) do
  446.                X1 := X1 + PTTT.Gap + length(Submenu[I].text[0]);
  447.            X1 := pred(X1) + PTTT.Gap ;
  448.        end
  449.        else
  450.           X1 := X1 + 2;
  451.        X2 := X1 + Submenu[No].width + 3;
  452.        If X2 > 80 then
  453.        begin
  454.            X1 := 80 - (X2 - X1) ;
  455.            X2 := 80;
  456.        end;
  457.        Y1 := succ(PTTT.TopY) + ord(PTTT.Style>0);
  458.        Y2 := Y1 + 1 + Submenu[No].total;
  459.        Fbox(X1,Y1,X2,Y2,PTTT.BorCol,PTTT.BCol,PTTT.Style);
  460.        Fastwrite(X1,succ(PTTT.TopY)+ord(PTTT.Style>0),attr(PTTT.BorCol,PTTT.BCol),Joinchar);
  461.        If X2 < PTTT.TopX + Main_wid then
  462.           Fastwrite(X2,succ(PTTT.TopY)+ord(PTTT.Style>0),attr(PTTT.BorCol,PTTT.BCol),Joinchar)
  463.        else
  464.        If X2 = PTTT.TopX + Main_wid then
  465.           Fastwrite(X2,succ(PTTT.TopY)+ord(PTTT.Style>0),attr(PTTT.BorCol,PTTT.BCol),Joinleftchar)
  466.        else
  467.        begin
  468.            Fastwrite(X2,PTTT.TopY+2,attr(PTTT.BorCol,PTTT.BCol),TRchar);
  469.            Fastwrite(PTTT.TopX+Main_wid,succ(PTTT.TopY)+ord(PTTT.Style>0),attr(PTTT.BorCol,PTTT.BCol),Joindownchar);
  470.        end;
  471.        For I := 1 to Submenu[PickM].total do
  472.            Display_Sub_Picks(I,2);
  473.        PickS := SubMenu[PickM].LastPick;
  474.        If not (PickS in [1..Submenu[PickM].Total]) then
  475.           PickS := 1;
  476.        Display_Sub_Picks(PickS,1);
  477.    end;  {proc Display_Sub_Menu}
  478.  
  479. begin     {Main Procedure Display_menu}
  480.     Set_Style;
  481.     Load_Menu_Parameters;
  482.     Save_Screen;
  483.     Finished := false;
  484.     If (PickM < 1) then
  485.        PickM := 1;
  486.     Display_Main_Menu;
  487.     For I := 1 to Tot_main do
  488.         Submenu[I].lastPick := 1;
  489.     SubMenu[PickM].LastPick := PickS;
  490.     If PickS <> 0 then
  491.     begin
  492.         Display_Sub_Menu(PickM);
  493.         Down := true;
  494.     end
  495.     else
  496.         Down := false;
  497.     Repeat
  498.           ChM := GetKey;
  499.           {$IFNDEF VER50}
  500.           If PM_UserHook <> nil then
  501.              If Down then
  502.                 CallFromPM(ChM,PickM,PickS)
  503.              else
  504.                 CallFromPM(ChM,PickM,0);
  505.           {$ENDIF}
  506.           {$IFDEF VER50}
  507.              If Down then
  508.                 PTTT.Hook(ChM,PickM,PickS)
  509.              else
  510.                 PTTT.Hook(ChM,PickM,0);
  511.           {$ENDIF}
  512.           Case upcase(ChM) of
  513.           'A'..'Z'   : If down then    {check if letter is first letter of menu option}
  514.                        begin
  515.                            Count := 0;
  516.                            Repeat
  517.                                 Count := succ(count);
  518.                                 ChT := First_Capital(Submenu[PickM].Text[count],Cap);
  519.                                 If ChT  = upcase(ChM) then
  520.                                 begin
  521.                                     Finished := true;
  522.                                     Display_Sub_Picks(PickS,0);
  523.                                     PickS := Count;
  524.                                     Display_Sub_Picks(PickS,1);
  525.                                 end;
  526.                            Until (Finished) or (count = submenu[PickM].Total);
  527.                        end
  528.                        else      {down false}
  529.                        begin
  530.                            Count := 0;
  531.                            Repeat
  532.                                 Count := succ(count);
  533.                                 ChT := First_Capital(Submenu[Count].Text[0],Cap);
  534.                                 If ChT = upcase(ChM) then
  535.                                 begin
  536.                                     Display_Main_Picks(PickM,0);
  537.                                     PickM := Count;
  538.                                     Down := true;
  539.                                     Display_Main_Picks(PickM,2);
  540.                                     If not (PickS in [1..Submenu[PickM].Total]) then
  541.                                        PickS := 1;
  542.                                     Display_Sub_Menu(PickM);
  543.                                 end;
  544.                            Until (Down) or (count = Tot_Main);
  545.                        end;
  546.           #133,          {Mouse Enter}
  547.           Enter      : If Down or (Submenu[PickM].Total = 0) then
  548.                        begin
  549.                           Finished := true;
  550.                           If Submenu[PickM].Total = 0 then PickS := 0;
  551.                        end
  552.                        else
  553.                        begin
  554.                            Down := true;
  555.                            Display_Main_Picks(PickM,2);
  556.                            Display_Sub_Menu(PickM);
  557.                        end;
  558.           #132,        {Mouse Esc}
  559.           Esc       :  If Down then
  560.                        begin
  561.                            IF not PTTT.AlwaysDown then
  562.                            begin
  563.                                Down := false;
  564.                                Remove_sub_menu;
  565.                                Display_Main_menu;
  566.                            end
  567.                            else
  568.                            begin
  569.                               If PTTT.AllowEsc then
  570.                               begin
  571.                                   Finished := true;
  572.                                   PickM := 0;
  573.                               end;
  574.                            end;
  575.                        end
  576.                        else
  577.                            If PTTT.AllowEsc then
  578.                            begin
  579.                                Finished := true;
  580.                                PickM := 0;
  581.                            end;
  582.           #0        :      begin
  583.                            end;
  584.           #131      :  If PickM < ToT_main then
  585.                        begin
  586.                            Display_main_picks(PickM,0);  {clear highlight}
  587.                            If Down then
  588.                               Remove_Sub_Menu;
  589.                            PickM := succ(PickM);
  590.                            Display_Main_Picks(PickM,1);
  591.                            If down then
  592.                               Display_Sub_Menu(PickM);
  593.                        end;
  594.           CursRight :  begin
  595.                            Display_main_picks(PickM,0);  {clear highlight}
  596.                            If Down then
  597.                               Remove_Sub_Menu;
  598.                            If PickM < ToT_main then
  599.                               PickM := PickM + 1
  600.                            else
  601.                               PickM := 1;
  602.                            Display_Main_Picks(PickM,1);
  603.                            If down then
  604.                                Display_Sub_Menu(PickM);
  605.                        end;
  606.           #130      :  If PickM > 1 then    {MouseLeft}
  607.                        begin
  608.                            Display_main_picks(PickM,0);  {clear highlight}
  609.                            If Down then
  610.                               Remove_Sub_Menu;
  611.                            PickM := pred(PickM);
  612.                            Display_Main_Picks(PickM,1);
  613.                            If down then
  614.                                Display_Sub_Menu(PickM);
  615.                        end;
  616.  
  617.           CursLeft  :  begin
  618.                            Display_main_picks(PickM,0);  {clear highlight}
  619.                            If Down then
  620.                               Remove_Sub_Menu;
  621.                            If PickM > 1 then
  622.                               PickM := pred(PickM)
  623.                            else
  624.                               PickM := Tot_Main;
  625.                            Display_Main_Picks(PickM,1);
  626.                            If down then
  627.                                Display_Sub_Menu(PickM);
  628.                        end;
  629.           #129       : If (Submenu[PickM].Total <> 0) then
  630.                        begin
  631.                            If Not Down then    {Mouse Down}
  632.                            begin
  633.                                Down := true;
  634.                                Display_Main_Picks(PickM,2);
  635.                                Display_Sub_Menu(PickM);
  636.                            end
  637.                            else
  638.                               If PickS < Submenu[PickM].Total then
  639.                               begin
  640.                                   Display_Sub_Picks(PickS,0);
  641.                                   PickS := succ(PickS);
  642.                                   Display_Sub_Picks(PickS,1);
  643.                               end;
  644.                        end;
  645.           CursDown   : If (Submenu[PickM].Total <> 0) then
  646.                        begin
  647.                            If Not Down then
  648.                            begin
  649.                                Down := true;
  650.                                Display_Main_Picks(PickM,2);
  651.                                Display_Sub_Menu(PickM);
  652.                            end
  653.                            else
  654.                            begin
  655.                                Display_Sub_Picks(PickS,0);
  656.                                If PickS < Submenu[PickM].Total then
  657.                                   PickS := succ(PickS)
  658.                                else
  659.                                   PickS := 1;
  660.                                Display_Sub_Picks(PickS,1);
  661.                            end;
  662.                        end;
  663.           #128       : If down and (Picks > 1) and (Submenu[PickM].Total <> 0) then  {fix 4.01}
  664.                        begin
  665.                            Display_Sub_Picks(PickS,0);
  666.                            PickS := pred(PickS);
  667.                            Display_Sub_Picks(PickS,1);
  668.                        end;
  669.           CursUp     : If (Submenu[PickM].Total <> 0) then
  670.                        begin
  671.                            If down then
  672.                            begin
  673.                                Display_Sub_Picks(PickS,0);
  674.                                If PickS <> 1  then
  675.                                   PickS := pred(PickS)
  676.                                else
  677.                                   PickS := Submenu[PickM].Total;
  678.                                Display_Sub_Picks(PickS,1);
  679.                            end;
  680.                        end;
  681.           EndKey    :  If (Submenu[PickM].Total <> 0) then
  682.                        begin
  683.                            If Down then
  684.                            begin
  685.                                Display_Sub_Picks(PickS,0);
  686.                                PickS := Submenu[PickM].Total;
  687.                                Display_Sub_Picks(PickS,1);
  688.                            end
  689.                            else
  690.                            begin
  691.                                Display_main_picks(PickM,0);  {clear highlight}
  692.                                PickM := ToT_Main;
  693.                                Display_main_picks(PickM,1);
  694.                            end;
  695.                        end
  696.                        else
  697.                        begin
  698.                            Display_main_picks(PickM,0);  {clear highlight}
  699.                            PickM := ToT_Main;
  700.                            Display_main_picks(PickM,1);
  701.                            If Down then
  702.                            begin
  703.                                Display_Main_Picks(PickM,2);
  704.                                Display_Sub_Menu(PickM);
  705.                            end;
  706.                        end;
  707.           HomeKey   :  If (Submenu[PickM].Total <> 0) then
  708.                        begin
  709.                            If Down then
  710.                            begin
  711.                                Display_Sub_Picks(PickS,0);
  712.                                PickS := 1;
  713.                                Display_Sub_Picks(PickS,1);
  714.                            end
  715.                            else
  716.                            begin
  717.                                Display_main_picks(PickM,0);  {clear highlight}
  718.                                PickM := 1;
  719.                                Display_main_picks(PickM,1);
  720.                            end;
  721.                        end
  722.                        else
  723.                        begin
  724.                            Display_main_picks(PickM,0);  {clear highlight}
  725.                            PickM := 1;
  726.                            Display_main_picks(PickM,1);
  727.                            If Down then
  728.                            begin
  729.                                Display_Main_Picks(PickM,2);
  730.                                Display_Sub_Menu(PickM);
  731.                            end;
  732.                        end;
  733.           end; {endcase}
  734.  Until Finished;
  735.  If PTTT.RemoveMenu Then
  736.     Restore_Screen;
  737.  Dispose_Screen;
  738.  end;  {end of main procedure Display_Menu}
  739.  
  740. begin
  741.     Horiz_Sensitivity := 4;   {cursors left and right before mouse returns}
  742.     Default_Settings;
  743. end.
  744.